Unidad 3: Herramientas para el análisis exploratorio de datos
Manejo y Visualización de Datos
Maestría en Estadística Aplicada - FCEyE - UNR
Parte 2: Tipos de visualización
Manejo y Visualización de Datos
Maestría en Estadística Aplicada - FCEyE - UNR
Parte 2: Tipos de visualización
1 Preparativos
En este apunte estaremos usando el sistema gráfico de ggplot2 (¡a repasar el apunte correspondiente si es necesario!).
A continuación se listan los paquetes que se usan a lo largo de este material. Corriendo las siguientes líneas se pueden cargar todos, instalando los que faltan.
paquetes <-
c("readr", "readxl", "dplyr", "tibble", "ggplot2", "cowplot", "tidyr",
"ggridges", "ggbeeswarm", "GGally", "rgl", "plotly", "treemapify", "car",
"vcd", "colorspace", "ggcleveland", "corrplot", "lubridate",
"gganimate", "gapminder", "forcats", "janitor", "ggforce")
# Instalar si no están
instalados <- paquetes %in% rownames(installed.packages())
if (any(instalados == FALSE)) {
install.packages(paquetes[!instalados])
}
# Cargarlos
invisible(lapply(paquetes, library, character.only = TRUE))
# Nada que ver con los paquetes, pero seteo un theme ahora para todos los plots
theme_set(theme_bw())Ahora vamos a mencionar diversos diagramas y gráficos que se usan comúnmente para visualizar datos, dependiendo del objetivo que se persiga.
Estaremos trabajando con el conjunto de datos
partos_rosario.csv, que contiene información sobre los partos atendidos en los efectores municipales de Rosario durante los años 2015 a 2018.Los datos fueron descargados del Portal de Datos Abiertos de la Municipalidad de Rosario.
Las variables disponibles son1:
- año: año del parto
- mes: mes del parto
- efector: Hospital Roque Sáenz Peña
(
HRSP) o Maternidad Martin (MM). - idmama: código de identificación de la madre
- idparto: código de identificación del parto
- edad_madre: edad de la madre en años
- rango_edad: edad de la madre categorizada en intervalos quinquenales
- rango_edad2: edad de la madre categorizada en intervalos de 10 años
- hijo: número que identifica a cada hijo nacido en el parto
- lugar: lugar donde ocurrió el parto
- parto: tipo de parto
- edad_gestacional_valor: edad gestacional categorizada del recién nacido en semanas completas
- edad_gestacional: edad gestacional categorizada del recién nacido en semanas completas, categorizada en intervalos.
- peso: peso en gramos del recién nacido
- sexo_bb: sexo del recién nacido (femenino =
F, masculino =M)
- Procedemos a la lectura del archivo:
datos <- read_csv("partos_rosario.csv")- Previsualización:
datos# A tibble: 20,943 × 15
año mes efector idmama idparto edad_madre rango_edad rango_edad2 hijo
<dbl> <dbl> <chr> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 2015 9 MM 2082 2084 11 10 a 14 años 10 a 19 1
2 2015 10 MM 2974 2976 12 10 a 14 años 10 a 19 1
3 2015 7 MM 2550 2552 14 10 a 14 años 10 a 19 1
4 2015 3 MM 5137 5139 13 10 a 14 años 10 a 19 1
5 2015 8 MM 5241 5243 10 10 a 14 años 10 a 19 1
6 2015 9 MM 5438 5440 10 10 a 14 años 10 a 19 1
7 2015 3 HRSP 195 195 14 10 a 14 años 10 a 19 1
8 2015 5 HRSP 230 230 14 10 a 14 años 10 a 19 1
9 2015 4 HRSP 533 534 14 10 a 14 años 10 a 19 1
10 2015 9 HRSP 570 571 13 10 a 14 años 10 a 19 1
# … with 20,933 more rows, and 6 more variables: lugar <chr>, parto <chr>,
# edad_gestacional_valor <dbl>, edad_gestacional <chr>, peso <dbl>,
# sexo_bb <chr>
2 Otras visualizaciones
2.1 Visualización en paneles (faceting)
- La visualización en paneles consiste en repetir el mismo gráfico para cada nivel de una variable adicional, o para cada combinación de niveles de más de una variable.
- Es un medio que permite aumentar rápidamente el número de variables visualizadas en una figura.
ggplot(datos) +
aes(x = rango_edad2, y = peso) +
geom_boxplot() +
facet_wrap(~ edad_gestacional, nrow = 1,
labeller = labeller(edad_gestacional = function(x) paste(x, "semanas"))) +
labs(x = "Edad de la madre", y = "Peso (g)",
title = "Peso de nacimiento\nsegún edad de la madre y semanas de gestación") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))- En el siguiente ejemplo se usan dos variables para definir los paneles:
ggplot(datos) +
aes(x = rango_edad2, y = peso) +
geom_boxplot() +
facet_grid(parto ~ edad_gestacional,
labeller = labeller(edad_gestacional = function(x) paste(x, "semanas"))) +
labs(x = "Edad de la madre", y = "Peso (g)",
title = "Peso de nacimiento\nsegún edad de la madre, semanas de gestación y tipo de parto") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))- A continuación vemos que no es necesario disponer los paneles en múltiples filas para mostrar la combinación de niveles entre dos variables:
ggplot(datos) +
aes(x = rango_edad2, y = peso) +
geom_boxplot() +
facet_grid(. ~ parto + sexo_bb) +
labs(x = "Edad de la madre", y = "Peso (g)",
title = "Peso de nacimiento según edad de la madre,\ntipo de parto y sexo del recién nacido") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))- Finalmente, vemos que las ideas anteriores pueden extenderse para separar en paneles teniendo en cuenta más de dos variables:
ggplot(datos) +
aes(x = rango_edad2, y = peso) +
geom_boxplot() +
facet_grid(edad_gestacional ~ parto + sexo_bb) +
labs(x = "Edad de la madre", y = "Peso (g)",
title = "Peso de nacimiento según edad de la madre,\ntipo de parto, edad gestacional y sexo del recién nacido") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))2.2 Paquete plotly
Plotly es una compañía canadiense fundada en 2013 que ofrece herramientas de visualización y data analytics (link a su web oficial) asociadas generalmente a lenguajes de programación como Python o JavaScript. Entre los muchos productos desarrollados por esta empresa se encuentra el paquete de R que lleva su nombre, orientado a generar visualizaciones dinámicas (link a las referencias).
Si bien este paquete ofrece numerosas posibilidades (ver galería) no todos tenemos tiempo para aprender a generar gráficos con una nueva sintaxis, lo que implicaría acostumbrarse a escribir nuevas estructuras, funciones, argumentos, opciones, etc. Por suerte para nosotros,
plotlyse integra perfectamente con nuestro viejo conocidoggplot2de manera muy simple.
datos_sub <- datos[1:500,]
# Creamos un gráfico de ggplot común y corriente
grafico <-
ggplot(datos_sub) +
aes(x = edad_gestacional_valor, y = peso, color = parto) +
geom_jitter(width = 0.5, height = 0, alpha = 0.5) +
labs(x = "Edad gestacional (semanas completas)", y = "Peso (g)",
color = "Tipo de parto")
grafico# Y lo convertimos en uno de plotly
ggplotly(grafico)# Para controlar lo que aparece como texto al pasar sobre los puntos:
datos_sub <- mutate(datos_sub,
etiqueta = paste0("Efector: ", efector, "\nEdad madre: ", edad_madre))
# Usamos la estética text
grafico <-
ggplot(datos_sub) +
aes(x = edad_gestacional_valor, y = peso, color = parto, text = etiqueta) +
geom_jitter(width = 0.5, height = 0, alpha = 0.5) +
labs(x = "Edad gestacional (semanas completas)", y = "Peso (g)",
color = "Tipo de parto")
# Muestra la info de todas las estéticas definidas
ggplotly(grafico)# Muestra la info de las estéticas especificadas en tooltip
ggplotly(grafico, tooltip = "text")2.3 Paquete gganimate
gganimatees una extensión deggplot2que ofrece herramientas para crear gráficos animados a partir de objetos ggplot. Este paquete es útil cuando queremos representar en un mismo gráfico diferentes períodos temporales, o bien destacar las diferencias entre distintos grupos de individuos.Veamos un ejemplo donde se aprecia la evolución a través de los años del PBI per cápita y la esperanza de vida de varios países según continente, tomando datos del paquete
gapminder.Los pasos a seguir para generar una animación en formato gif son:
- Crear un gráfico de manera corriente con
ggploty agregar una capa extra con alguna de las funciones transition de gganimate, la cual crea un gráfico diferente para cada valor de la variable establecida - Generar un objeto “animado” mediante la función
animate(), eligiendo la cantidad de fotogramas - Guardar el objeto animado en un archivo en nuestra PC, con formato
gif, utilizando la función
anim_save()
- Crear un gráfico de manera corriente con
# Hacemos un gráfico básico
g <-
ggplot(data = gapminder) +
aes(x = log(gdpPercap), y = lifeExp, size = pop, colour = country) +
geom_point(alpha = 0.7, show.legend = FALSE)
g# Imaginar cada paso de la animación como algo que se podría graficar en paneles...
g + facet_wrap(~year)# Entonces sólo tenemos que intercambiar la capa de paneles por una de
# transición animada
g + transition_time(year)- Ahora le agregamos algunos detalles, usamos la función
animate()para especificar opciones referidas a la generación del gif (cantidad de frames, duración, etc.) y la funciónanim_save()para guardar un archivo con la animación:
g <-
ggplot(data = gapminder) +
aes(x = log(gdpPercap), y = lifeExp, size = pop, colour = country) +
geom_point(alpha = 0.7, show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
facet_wrap(~continent) +
labs(title = 'Año: {frame_time}',
x = 'Logaritmo del PBI per Cápita',
y = 'Esperanza de Vida (en años)') +
theme_bw() +
theme(axis.title = element_text(face = "bold")) +
transition_time(year) + #Variable de Transición
ease_aes('linear') #Tipo de Transición
animacion <- animate(Grafico,
renderer = gifski_renderer(),
nframes = 50) # Cantidad de fotogramas
# Guardo la animación en un archivo formato gif
anim_save(filename = "Gapminder.gif",
animation = animacion)Gráfico animado con gganimate según año
- Otro ejemplo:
2.4 Visualizaciones en 3D
Si bien hoy existen muchos paquetes de software que facilitan la visualización de datos trivariados, no debe olvidarse que de todas formas el resultado para nuestra vista es siempre una representación en dos dimensiones y su interpretación es altamente dependiente del ángulo elegido.
Por eso, muchos autores no recomiendan su uso.
ggplot2por sí solo no posee la capacidad de renderizar gráficos dinámicos en 3D.Una opción es el paquete
rgl:Otra alternativa es el paquete
plotly.
plot_ly(data = datos_sub,
x = ~edad_gestacional_valor,
y = ~edad_madre,
z = ~peso,
type = "scatter3d", mode = "markers", size = 0.5) %>%
layout(
scene = list(
xaxis = list(title = "Edad gestacional (semanas)"),
yaxis = list(title = "Edad de la madre (años)"),
zaxis = list(title = "Peso (g)")
))En los datos originales, sólo está disponible la edad de la madre en agrupada en quinquenios y la edad gestacionales en intervalos de semanas. Con fines didácticos se simularon los valores cuantitativos edad_madre y edad_gestacional_valor. Además, se eliminaron casos sensibles de edades gestacionales pequeñas.↩︎